package org.budo.sound.util;

import java.util.ArrayList;
import java.util.List;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.Line;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.spi.MixerProvider;

import com.sun.media.sound.JDK13Services;

/**
 * 音频设备工具类
 * 
 * @author limingwei
 */
public class MixerUtil { //
    public static final AudioFormat MICRO_PHONE_AUDIO_FORMAT = new AudioFormat(16000.0F, 16, 1, true, false);

    private static final AudioFormat CLIP_AUDIO_FORMAT = new AudioFormat( //
            AudioFormat.Encoding.PCM_SIGNED, AudioSystem.NOT_SPECIFIED, 16, 2, 4, AudioSystem.NOT_SPECIFIED, true);

    /**
     * 用以筛选 可用于 Clip 播放的 Mixer.Info
     */
    private static final javax.sound.sampled.DataLine.Info CLIP_MIXER_INFO = new DataLine.Info(Clip.class, CLIP_AUDIO_FORMAT);

    /**
     * 返回所有 Mixer
     */
    public static List<Mixer> getMixers() {
        List<MixerProvider> providers = (List<MixerProvider>) JDK13Services.getProviders(MixerProvider.class);
        List<Mixer> mixes = new ArrayList<Mixer>();

        for (MixerProvider mixerProvider : providers) {
            Mixer.Info[] providerInfos = mixerProvider.getMixerInfo();
            for (Mixer.Info providerInfo : providerInfos) {
                Mixer mixer = mixerProvider.getMixer(providerInfo);

                mixes.add(mixer);
            }
        }

        return mixes;
    }

    /**
     * 返回支持 指定 Line.Info 的 Mixer
     */
    public static List<Mixer> getLineSupportedMixers(Line.Info lineInfo) {
        List<Mixer> mixers = getMixers();
        List<Mixer> list = new ArrayList<Mixer>();

        for (Mixer mixer : mixers) {
            if (mixer.isLineSupported(lineInfo)) {
                list.add(mixer);
            }
        }
        return list;
    }

    /**
     * 返回一组 Mixer 的 Info
     */
    public static List<Mixer.Info> getMixerInfos(List<Mixer> mixers) {
        List<Mixer.Info> infos = new ArrayList<Mixer.Info>();
        for (Mixer mixer : mixers) {
            infos.add(mixer.getMixerInfo());
        }
        return infos;
    }

    /**
     * 返回可用于 Clip 播放的 Mixer.Info
     */
    public static List<Mixer.Info> getClipMixerInfos() {
        List<Mixer> mixers = getLineSupportedMixers(CLIP_MIXER_INFO);
        return getMixerInfos(mixers);
    }

    /**
     * 返回所有 Mixer.Info
     */
    public static List<Mixer.Info> getMixerInfos() {
        List<Mixer> mixers = getMixers();
        return getMixerInfos(mixers);
    }

    /**
     * 根据设备名称查找指定 Mixer.Info
     */
    public static Mixer.Info getClipMixerInfoByName(String name) {
        List<Mixer.Info> infos = getClipMixerInfos();
        for (Mixer.Info info : infos) {
            if (info.getName().equals(name)) {
                return info;
            }
        }

        return null;
    }
}